package com.zfsn.okaria.viewbinding

import android.content.Context
import androidx.fragment.app.Fragment
import com.elvishew.xlog.XLog

/**
 * 解决fragment 中多层嵌套造成 可见性变化判断和懒加载问题
 */
abstract class VisibilityFragment : Fragment()  , IFragmentVisibility {
    // Fragment当前是否对用户可见。
    private var mIsFragmentVisible = false
    // Fragment当前是否是第一次对用户可见。
    private var mIsFragmentVisibleFirst = true
    override fun onResume() {
        super.onResume()
        determineFragmentVisible()
    }
    override fun onPause() {
        super.onPause()
        determineFragmentInvisible()
    }
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (hidden) {
            determineFragmentInvisible()
        } else {
            determineFragmentVisible()
        }
    }
    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        if (isVisibleToUser) {
            determineFragmentVisible()
        } else {
            determineFragmentInvisible()
        }
    }
    override fun isVisibleToUser(): Boolean = mIsFragmentVisible
    override fun onAttach(context: Context) {
        super.onAttach(context)
//        XLog.i("生命周期: onAttach ${selfFlag()}  ")
    }

    override fun onVisible() {
        super.onVisible()
//        XLog.i(this.javaClass.simpleName,"生命周期:显示： onVisible")
//        XLog.i("生命周期: onVisible ${selfFlag()}  ")
    }

    override fun onVisibleFirst() {
        super.onVisibleFirst()
        XLog.i("生命周期 可见 %s", "onVisibleFirst ${selfFlag()}  ")
    }

    override fun onVisibleExceptFirst() {
        super.onVisibleExceptFirst()
        XLog.i("生命周期 可见 onVisibleExceptFirst ${selfFlag()}  ")
    }

    override fun onInvisible() {
        super.onInvisible()
        XLog.i("生命周期 不可见 ${selfFlag()}  ")
    }

    open fun selfFlag():String{
        return this.javaClass.simpleName
    }

    private fun determineFragmentVisible() {
        val parent = parentFragment
        if (parent != null && parent is VisibilityFragment) {
            if (!parent.isVisibleToUser()) {
                // Parent Fragment is invisible, child fragment must be invisible.
                return
            }
        }
        if (isResumed && !isHidden && userVisibleHint && !mIsFragmentVisible) {
            mIsFragmentVisible = true
            onVisible()
            if (mIsFragmentVisibleFirst) {
                mIsFragmentVisibleFirst = false
                onVisibleFirst()
            } else {
                onVisibleExceptFirst()
            }
            determineChildFragmentVisible()
        }
    }
    private fun determineFragmentInvisible() {
        if (mIsFragmentVisible) {
            mIsFragmentVisible = false
            onInvisible()
            determineChildFragmentInvisible()
        }
    }

    private fun determineChildFragmentVisible() {
        childFragmentManager.fragments.forEach {
            if (it is VisibilityFragment) {
                it.determineFragmentVisible()
            }
        }
    }

    private fun determineChildFragmentInvisible() {
        childFragmentManager.fragments.forEach {
            if (it is VisibilityFragment) {
                it.determineFragmentInvisible()
            }
        }
    }
}